package com.yeskery.nut.script;

import com.yeskery.nut.core.Controller;
import com.yeskery.nut.core.Method;
import com.yeskery.nut.script.function.FunctionExecutor;
import com.yeskery.nut.script.parser.ScriptParseException;

import java.lang.reflect.Proxy;
import java.util.Map;
import java.util.Optional;

/**
 * 基于元数据的控制器脚本
 * @author sprout
 * 2022-05-14 14:50
 */
public class MetadataControllerScript implements ControllerScript {

    /** id */
    private final long id;

    /** 方法元数据 */
    private final Map<Method, Metadata> metadataMap;

    /** 函数执行器 */
    private final FunctionExecutor functionExecutor;

    /**
     * 构建基于元数据的控制器脚本
     * @param id id
     * @param metadataMap 方法元数据
     * @param functionExecutor 函数执行器
     */
    public MetadataControllerScript(long id, Map<Method, Metadata> metadataMap, FunctionExecutor functionExecutor) {
        this.id = id;
        this.metadataMap = metadataMap;
        this.functionExecutor = functionExecutor;
    }

    @Override
    public ControllerPath toController() {
        ScriptController controller = new ScriptController();
        Controller proxyController = (Controller) Proxy.newProxyInstance(controller.getClass().getClassLoader(),
                controller.getClass().getInterfaces(),
                new ScriptControllerInvocationHandler(metadataMap, functionExecutor, controller));
        ControllerPath controllerPath = new ControllerPath();
        controllerPath.setController(proxyController);
        Optional<Metadata> optional = metadataMap.values().stream().findFirst();
        if (!optional.isPresent()) {
            throw new ScriptParseException("Script Metadata Paths Missing.");
        }
        controllerPath.setPaths(optional.get().getPaths());
        return controllerPath;
    }

    @Override
    public long getId() {
        return id;
    }

    @Override
    public String getName() {
        return "Nut-Script$" + id;
    }
}
